home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir24 / jnos110g.zip / FORWARD.C < prev    next >
C/C++ Source or Header  |  1994-07-05  |  43KB  |  1,277 lines

  1. /* Some of the code in this file was originally based on the following file:
  2.  * gateway.c : Paul Healy, EI9GL, 900818
  3.  *
  4.  * Rewrote forwarding mechanism to use "X-Forwarded-To" paradigm instead of
  5.  * "X-BBS-To", added timer support, etc.  Anders Klemets, SM0RGV, 901009.
  6.  */
  7.  /* Mods by G1EMM and WG7J */
  8. #include <ctype.h>
  9. #include <time.h>
  10. #include "global.h"
  11. #ifdef MBFWD
  12. #include "bm.h"
  13. #include "mailbox.h"
  14. #include "smtp.h"
  15. #include "cmdparse.h"
  16. #include "proc.h"
  17. #include "socket.h"
  18. #include "timer.h"
  19. #include "usock.h"
  20. #include "netuser.h"
  21. #include "ax25.h"
  22. #include "netrom.h"
  23. #include "nr4.h"
  24. #include "files.h"
  25. #include "index.h"
  26.   
  27. extern int MbForwarded;
  28. extern char MboxId[];
  29. #define ISPROMPT(s) (strlen(s) > 1 && s[strlen(s)-2] == '>')
  30. static struct timer fwdtimer;
  31. static struct proc *FwdProc;
  32.   
  33. static char *findident __ARGS((char *str, int n, char *result));
  34. static void sendmsg __ARGS((struct fwd *f,int msgn));
  35. static char *mbxtime __ARGS((time_t date));
  36. static int fwdinit __ARGS((struct mbx *m));
  37. static char *fwdanybbs __ARGS((struct mbx *m,int *poll));
  38. static int timeok __ARGS((char *line));
  39. static void fwdtick __ARGS((void *v));
  40. static void fwdproc __ARGS((void));
  41. static int isconnbbs __ARGS((struct mbx *m));
  42. static void startfwd __ARGS((int a,void *v1,void *v2));
  43. static int openconn __ARGS((int argc,char *argv[],void *p));
  44. static int sendmsgtobbs __ARGS((struct fwd *f,int msgn,char *dest));
  45. static int makecl __ARGS((struct fwd *f,int msgn,char *dest,char *line,char **subj,int *bul));
  46. static char *grabtext __ARGS((char *from,char *to,int marker));
  47.   
  48. /***************************************************************************
  49.    findident copies the 'n'th alphanumeric sequence from 'str' to result.
  50.    It returns a ptr to result. It returns "\0" for missing identifier etc.
  51.    Uses isalnum macro to decide on alphanumeric/non-alnum status.
  52. */
  53. static char *
  54. findident(str, n, result)
  55. char *str, *result;
  56. int n;
  57. {
  58.     int count; /* current identifier */
  59.     count = 0;
  60.     *result = '\0';
  61.     while ( (count<n) && (*str!='\0') ) { /* Process alnum or non alnum seq */
  62.         while ( (*str!='\0') && (!isalnum(*str)) ) /* Get rid of ';:.@%"# etc */
  63.             str++;
  64.         if ( (*str!='\0') && isalnum(*str) ) { /* this is an alnum seq */
  65.             count++;
  66.             while ( (*str!='\0') && (isalnum(*str) || (*str=='_')) )
  67.                 if (count==n)
  68.                     *result++ = *str++;
  69.                 else str++;
  70.             if (count==n)
  71.                 *result = '\0';
  72.         }
  73.     }
  74.     return result;
  75. }
  76. /**************************************************************************/
  77. /* sendmsg() modified to send the R: line always.
  78.  * also added some additional strings like qth and zipcode etc. to R: line.
  79.  * Original SMTP headers get forwarded optionally.
  80.  * 920114 - WG7J
  81.  */
  82. extern char *Mbhaddress;
  83. extern char *Mbfwdinfo;
  84. extern char *Mbqth;
  85. extern char *Mbzip;
  86. extern int Mbsmtptoo;
  87. extern int UtcOffset;
  88. extern int Mbheader;
  89. extern char shortversion[];
  90.   
  91. static void
  92. sendmsg(f,msgn)
  93. struct fwd *f;
  94. int msgn;
  95. {
  96.     struct mbx *m = f->m;
  97.     int i,rheader = 0;
  98.     long start;
  99.     char buf[LINELEN], tb[LINELEN], *cp;
  100.   
  101.     /* If the data part of the message starts with "R:" the RFC-822
  102.      * headers will not be forwarded. Instead we will add an R:
  103.      * line of our own.
  104.      */
  105.     /* ALWAYS forward with "R:" line - WG7J */
  106.     /* Now conditional upon Mbheader - 921201, WG7J */
  107.     if(Mbheader) {
  108.         /* First send recv. date/time and bbs address */
  109.         usprintf(m->user,"R:%s",mbxtime(f->ind.mydate));
  110.         /* If exists, send H-address */
  111.         if(Mbhaddress != NULLCHAR)
  112.             usprintf(m->user," @:%s",Mbhaddress);
  113.         /* location, if any */
  114.         if(Mbqth != NULLCHAR)
  115.             usprintf(m->user," [%s]",Mbqth);
  116.         /*if there is info, put it next */
  117.         if(Mbfwdinfo != NULLCHAR)
  118.             usprintf(m->user," %s",Mbfwdinfo);
  119.         /* number of the message */
  120.         usprintf(m->user," #:%lu",f->ind.msgid);
  121.         /* The BID, is any */
  122.         if(f->bid[0] != '\0')
  123.             usprintf(m->user," $:%s",&f->bid[1]);
  124.         /* zip code of the bbs */
  125.         if(Mbzip != NULLCHAR)
  126.             usprintf(m->user," Z:%s",Mbzip);
  127.         usputc(m->user,'\n');
  128.     }
  129.   
  130.     /* Open the mailbox file */
  131.     sprintf(buf,"%s/%s.txt",Mailspool,m->area);
  132.     if((m->mfile = fopen(buf,"r")) == NULL) {
  133.         usputs(m->user,"Can not find message body!\n");
  134. #ifdef MAILERROR
  135.         mail_error("MBX FWD %s: Can not find mailfile for msg %d in %s", \
  136.         m->name,msgn,buf);
  137. #endif
  138.         return;
  139.     }
  140.   
  141.     /* point to start of this message in file */
  142.     start = m->mbox[msgn].start;
  143.     fseek(m->mfile,start,SEEK_SET);
  144.   
  145.     /* If we also send the smtp headers, now see if the message
  146.      * has any R: headers. If so, send them first.
  147.      */
  148.     if(Mbsmtptoo) {
  149.         while(fgets(buf,sizeof(buf),m->mfile) != NULL) {
  150.             if(*buf == '\n')
  151.                 break;          /* End of smtp headers */
  152.         }
  153.         if(ferror(m->mfile))
  154.             return;
  155.         /* Found start of msg text, check for R: lines */
  156.         while(fgets(buf,sizeof(buf),m->mfile) != NULL &&
  157.         !strncmp(buf,"R:",2)) {
  158.             rheader = 1;
  159.             usputs(m->user,buf);
  160.         }
  161.         /* again point to start of this message in file */
  162.         fseek(m->mfile,start,SEEK_SET);
  163.     }
  164.   
  165.     /* Go past the SMTP headers to the data of the message.
  166.      * Check if we need to forward the SMTP headers!
  167.      * 920114 - WG7J
  168.      */
  169.     if(Mbsmtptoo && (rheader || Mbheader))
  170.         usputc(m->user,'\n');
  171.     while(fgets(buf,sizeof(buf),m->mfile) != NULL &&
  172.     *buf != '\n') {
  173.         if(Mbsmtptoo) {
  174.             /* YES, forward SMTP headers TOO !*/
  175.             switch(htype(buf)) {
  176.                 case XFORWARD: /* Do not forward the "X-Forwarded-To:" lines */
  177.                 case STATUS:   /* Don't forward the "Status:" line either */
  178.                 case BBSTYPE:
  179.                 case SUBJECT:
  180.                 case TO:
  181.                 case DATE:
  182.                     break;
  183.                 case FROM:
  184.                 /* Don't forward the "From: " line either.
  185.                  * make it ">From: "
  186.                  */
  187.                     usputc(m->user,'>');
  188.                 /*note fall-through*/
  189.                 default:
  190.                     if(!strncmp(buf,"From ",5))
  191.                         usputc(m->user,'>');
  192.                     usputs(m->user,buf);
  193.             }
  194.         }
  195.     }
  196.   
  197.     /* Now we are at the start of message text.
  198.      * the rest of the message is treated below.
  199.      * Remember that R: lines have already been sent,
  200.      * if we sent smtp headers !
  201.      */
  202.     i = 1;
  203.   
  204.     while(fgets(buf,sizeof(buf),m->mfile) != NULL &&
  205.     strncmp(buf,"From ",5)) {
  206.         if(i) {
  207.             if(!strncmp(buf,"R:",2)) {
  208.                 if(Mbsmtptoo) continue;
  209.             } else {
  210.                 i = 0;
  211.                 if(*buf != '\n')
  212.                     /* Ensure body is separated from R: line */
  213.                     usputc(m->user,'\n');
  214.             }
  215.         }
  216.         usputs(m->user,buf);
  217.     }
  218.     fclose(m->mfile);
  219.     m->mfile = NULL;
  220.     return;
  221. }
  222.   
  223. /* Parse a line for date and time in Arpanet format
  224.  * (Day, day Month year hh:mm:ss Zone) and return it in mailbox format
  225.  * (yymmdd/hhmmz)
  226.  */
  227. static char *
  228. mbxtime(time_t date) {
  229.     time_t cdate;   /* Date corrected for timezone offset */
  230.     extern char *Months[];
  231.     static char buf[13];
  232.     char *cp;
  233.     int month;
  234.   
  235.     cdate = date;
  236.     /* adjust for GMT/UTC time - WG7J */
  237.     if(UtcOffset != 0)
  238.         cdate -= UtcOffset*3600L;
  239.     cp = ctime(&cdate);
  240.   
  241.     /* Check month */
  242.     for(month=0; month < 12; ++month)
  243.         if(strnicmp(Months[month],cp+4,3) == 0)
  244.             break;
  245.     if(month == 12)
  246.         return NULL;
  247.     month++;
  248.   
  249.     sprintf(buf,"%2.2s%02d%2.2s/%2.2s%2.2sz",cp+22,month,cp+8,cp+11,cp+14);
  250.     return buf;
  251. }
  252.   
  253. static char *
  254. grabtext(from, to, marker)
  255. char *from, *to;
  256. int marker;
  257. {
  258.     while (*from!=marker)
  259.         *to++ = *from++;
  260.     *to = '\0';
  261.     return from+1;
  262. }
  263.   
  264. /* Makes a command line and returns -1 if the message cannot be sent */
  265. static int
  266. makecl(f, msgn, dest, line, subj, bul)
  267. struct fwd *f;
  268. int msgn;               /* Message number */
  269. char *dest;             /* Destination address to use instead of To: line */
  270. char *line, **subj;      /* Buffers to keep command line and subject */
  271. int *bul;       /* True if message is in public message area */
  272. {
  273.     struct mbx *m = f->m;
  274.     struct let *cmsg = &m->mbox[msgn];
  275.     struct mailindex *ind = &f->ind;
  276.     struct fwdbbs *bbs;
  277.     int bulletin = *bul;
  278.     int foundbid = 0;
  279.     char *cp;
  280.     char *to,*atbbs;
  281.     char bid[60];
  282.   
  283.     if((cmsg->status & BM_HOLD) || (!bulletin && (cmsg->status & BM_READ)))
  284.         return -1;      /* the message was on hold or already read */
  285.   
  286.     /* The following code tries to parse the "To: " line where the
  287.      * address looks like "to", "to@atbbs", or "to%atbbs@host"
  288.      */
  289.     to = ind->to;
  290.     if((atbbs = strchr(to,'%')) != NULL) {
  291.         *atbbs++ = '\0';    /* "to" ends at the '%' character */
  292.         /* Now get rid of the following '@host' field */
  293.         if((cp = strchr(atbbs,'@')) != NULL)
  294.             *cp = '\0';
  295.     }
  296.     if((cp = strchr(to,'@')) != NULL) {
  297.         *cp = '\0';   /* "to" or "atbbs" ends at the '@' character */
  298.         if(!atbbs)
  299.             atbbs = cp + 1;
  300.     }
  301.     /*
  302.     if(!atbbs )
  303.         atbbs = to;
  304.      */
  305.   
  306.     /* "to" or "atbbs" should not be more than 6 characters (ALEN).
  307.      * If "to" is too long, it might simply be because the area name
  308.      * is longer than 6 characters, but it might also be because
  309.      * the address on the To: line is in an obscure format that we
  310.      * failed to parse (eg '!' character notation.)
  311.      */
  312.     if(strlen(to) > ALEN) {
  313.         /* Play safe and set "to" and "atbbs" to the area name */
  314.         to = m->area;
  315.         atbbs = m->area;
  316.     }
  317.     to=strdup(to);
  318.     atbbs=strdup(atbbs);
  319.     if(strlen(to) > ALEN)
  320.         to[ALEN] = '\0';    /* Maximum length is 6 */
  321.   
  322.     /* Only if the BBS supports "hierarchical routing designators"
  323.      * is the atbbs field allowd to be longer than 6 characters and
  324.      * have dots in it.
  325.      */
  326.     if((m->sid & MBX_HIER_SID) == 0) {
  327.         if(atbbs && strlen(atbbs) > ALEN)
  328.             atbbs[ALEN] = '\0';    /* 6 character limit */
  329.         if(atbbs && (cp = strchr(atbbs,'.')) != NULLCHAR)
  330.             *cp = '\0';       /* cut "atbbs" at first dot */
  331.     }
  332.   
  333.     /* The following code distinguishes between three different types
  334.      * of Message-IDs: abcde@callsign.bbs, abcde@otherhost.domain,
  335.      * and abcde@ourhost.domain.
  336.      * The first type is converted to $abcde and the second to
  337.      * $abcde_host.domain. The last to $abcde_first-part-of-H-address.
  338.      * This preserves compability with BBSes.
  339.      */
  340.     f->bid[0] = '\0';
  341.     strncpy(&bid[1],ind->messageid,sizeof(bid) - 1);
  342.     bid[sizeof(bid)-1] = '\0';
  343.     /* Is there a @hostname part ? */
  344.     if((cp = strchr(&bid[1],'@')) != NULL) {
  345.         bid[0] = '$';
  346.         if(stricmp(cp+strlen(cp) - 4, ".bbs") == 0) {
  347.             /*retain the bid given by user*/
  348.             *cp = '\0';
  349.             foundbid = 1; /* Indicate we found a 'real' bid - WG7J */
  350.         } else {
  351.             *cp++ = '_';
  352.             if(Mbhaddress && !strcmp(cp,Hostname)) {
  353.                 /* This is one of our messages!
  354.                  * Take the _host part from the H-address,
  355.                  * to form our bid - WG7J 930205
  356.                  */
  357.                 strcpy(cp,Mbhaddress);
  358.             }
  359.             /* This is now either $msg#@my_h-address, or $msg#_host.domain
  360.              * make this BID style '$msg#_host'
  361.              * ie. cut off after first period - WG7J
  362.              */
  363.             if((cp = strchr(cp,'.')) != NULL)
  364.                 *cp = '\0';
  365.   
  366.         }
  367.         bid[13] = '\0';     /* BIDs should be no longer than 13 bytes */
  368.         strcpy(f->bid,bid);
  369.     }
  370.   
  371.     if(ind->from) {
  372.         if((cp=strchr(ind->from,'@')) != NULL)
  373.             *cp = '\0';
  374.         if((cp=strchr(ind->from,'%')) != NULL)
  375.             *cp = '\0';
  376.         if(strstr(ind->from,m->name) != NULL) {
  377.             /* This message came from the connected BBS so Abort */
  378.             free(to);
  379.             free(atbbs);
  380.             return -1;
  381.         }
  382.         if(strlen(ind->from) > ALEN)
  383.             ind->from[ALEN] = '\0';      /* 6 character limit */
  384.     }
  385.   
  386.     if((*to == '\0' && ((dest != NULL && *dest == '\0') ||
  387.     dest == NULL)) || *ind->from == '\0') {
  388.         free(to);
  389.         free(atbbs);
  390.         return -1;
  391.     }
  392.   
  393.     if(line != NULL) {
  394.         if(dest != NULL && *dest != '\0'){
  395.             /* strip off hierarchical routing designators from the predefined
  396.              * destination address if they are not supported
  397.              */
  398.             if((m->sid & MBX_HIER_SID) == 0 && (cp = strchr(dest,'.')) !=
  399.                 NULLCHAR)
  400.                 *cp = '\0';
  401.             sprintf(line, "S%c %s < %s ", ind->type, dest, ind->from);
  402.         } else {
  403.             if(atbbs)
  404.                 sprintf(line, "S%c %s @ %s < %s ", ind->type, to, atbbs, ind->from);
  405.             else
  406.                 sprintf(line, "S%c %s < %s ", ind->type, to, ind->from);
  407.         }
  408.         /* Add the bid to bulletins,
  409.          * AND ALSO to anything that came in with a bid !
  410.          * Takes care off duplicate 'SP SYSOP@xxx $BID' problems.
  411.          * ALSO add it to ALL messages if the remote system supports MID's - WG7J
  412.          */
  413.         if((m->sid & MBX_MID) || ((bulletin || foundbid) & (m->sid & MBX_SID)))
  414.             strcat(line,f->bid);
  415.         strcat(line,"\n");
  416.     }
  417.     if(subj)
  418.         *subj = strdup(ind->subject);
  419.     free(to);
  420.     free(atbbs);
  421.     return 0;
  422. }
  423.   
  424. static int /* 0 = ok, -1 = problem so disc */
  425. sendmsgtobbs(f, msgn, dest)
  426. struct fwd *f;
  427. int msgn;
  428. char *dest;             /* Optional destination address to override To: line */
  429. {
  430.     int result = -1;
  431.     struct mbx *m = f->m;
  432.     struct fwdbbs *bbs;
  433.     int bulletin = (m->areatype == AREA);
  434.     char *subj = NULL;
  435.     char line[64];
  436.   
  437.     /* Check x-forwarded-to fields */
  438.     for(bbs=f->ind.bbslist;bbs;bbs=bbs->next)
  439.         if(!stricmp(bbs->call,m->name))
  440.             return 0;
  441.   
  442.     if(makecl(f, msgn, dest, line, &subj, &bulletin) == -1)
  443.         return 0;       /* do not forward this particular message */
  444.   
  445.     tputs(line);          /* Send mail offer to bbs */
  446. /*    rip(line); */
  447.     usflush(m->user);
  448.     if(recvline(m->user, m->line, MBXLINE) != -1 ) {
  449.         if(m->line[0] == 'O' || m->line[0] == 'o' || (m->sid & MBX_SID) == 0) {
  450.             /* Got 'OK' or any line if the bbs is unsofisticated */
  451.             tprintf("%s\n", subj);
  452.             sendmsg(f,msgn);   /* send the message */
  453. #ifdef FWDCTLZ
  454.             /* Some bbs code doesn't like /EX too well... */
  455.             tputs("\032\n");
  456. #else
  457.             tputs("/EX\n"); /* was 0x1a */
  458. #endif
  459.             usflush(m->user);
  460.             /* get F> for a good deliver */
  461.             while (recvline (m->user, m->line, MBXLINE) != -1 ) {
  462.                 if(ISPROMPT(m->line)) {
  463.                     rip(line);  /* N5KNX: now drop NL for nicer log entry */
  464.                     log(m->user,"MBOX bbs mail sent: %s ", line);
  465.                     if(m->areatype == AREA)
  466.                         m->mbox[msgn].status |= BM_FORWARDED;
  467.                     else
  468.                         m->mbox[msgn].status |= BM_DELETE;
  469.                     m->change = 1;
  470.                     result = 0;
  471.                     MbForwarded++;
  472.                     break;
  473.                 }
  474.             }
  475.         } else { /* OK response not received from bbs */
  476.             if (m->line[0] == 'N' || m->line[0] == 'n') { /* 'NO' respone */
  477.                 rip(m->line);   /* N5KNX: nicer log entry */
  478.                 log(m->user,"MBOX bbs mail refused: %s\t%s",line,m->line);
  479.                 /* Mark refused message as forwarded if it is a bulletin.
  480.                  * The message was probably a duplicate. Non-bulletin
  481.                  * messages are sent without BID, so they cannot be dected
  482.                  * as duplicates. The reason why it was refused is probably
  483.                  * because the address was invalid. Retry later.
  484.                  *
  485.                  * After lots of complaining, this behaviour is changed:
  486.                  * ALL messages that get the NO reply are marked
  487.                  * as forwarded ! - WG7J 930124
  488.                  */
  489.                 if(m->areatype == AREA)
  490.                     m->mbox[msgn].status |= BM_FORWARDED;
  491.                 else
  492.                     m->mbox[msgn].status |= BM_DELETE;
  493.                 m->change = 1;
  494.                 /* Count this as forwarded ! - WG7J */
  495.                 MbForwarded++;
  496.             }
  497.             /* should get a F> here */
  498.             while (recvline (m->user, m->line, MBXLINE) != -1 ) {
  499.                 if (ISPROMPT(m->line)) {
  500.                     result = 0;
  501.                     break;
  502.                 }
  503.             }
  504.         }
  505.     } /* OK or NO here */
  506.     free(subj);
  507.     return result;
  508. }
  509.   
  510. /* This is the main entry point for reverse forwarding. It is also used
  511.  * for normal, "forward", forwarding.
  512.  */
  513. int
  514. dorevfwd(argc,argv,p)
  515. int argc;
  516. char *argv[];
  517. void *p;
  518. {
  519.     char *cp, *dp;
  520.     int i, idx, err = 0;
  521.     struct fwd f;
  522.     struct indexhdr hdr;
  523.     struct fwdbbs *bbs;
  524.     char fn[64];
  525.     char oldarea[64];
  526.   
  527.     long before,after;
  528.   
  529.     f.m = (struct mbx *)p;
  530.     memset(&f.ind,0,sizeof(struct mailindex));
  531.   
  532.     log(f.m->user,"MBOX forwarding mail to: %s ", f.m->name);
  533.     /* indicate we are doing reverse forwarding, if we are not already
  534.      * doing normal forwarding.
  535.      */
  536.     if(f.m->state != MBX_FORWARD)
  537.         f.m->state = MBX_REVFWD;
  538.   
  539.     if(fwdinit(f.m) != -1) {
  540.         strcpy(oldarea,f.m->area);
  541.         while(!err && fgets(f.m->line,MBXLINE,f.m->tfile) != NULLCHAR) {
  542.             pwait(NULL);
  543.             if(*f.m->line == '-')     /* end of record reached */
  544.                 break;
  545.             cp = f.m->line;
  546.             rip(cp);           /* adds extra null at end */
  547.             /* skip spaces */
  548.             while(*cp && (*cp == ' ' || *cp == '\t'))
  549.                 cp++;
  550.             if(*cp == '\0' || *cp == '.' || *cp == '#' || *cp == '+' || *cp == '&' || *cp == '@')
  551.                 continue;    /* ignore empty or connect-script lines */
  552.             /* find end of area name, and beginning of optional destination string */
  553.             for (dp=cp; *dp && *dp != ' ' && *dp != '\t' && *dp != '\n'; dp++) ;
  554.             if (*dp) *dp++ = '\0';
  555.             changearea(f.m,cp);
  556.             /* Now create the index filename */
  557.             sprintf(fn,"%s/%s.ind",Mailspool,cp);
  558.   
  559.             /* strip leading blanks from dest */
  560.             cp=dp;
  561.             while(*cp && (*cp == ' ' || *cp == '\t'))
  562.                 cp++;
  563.             /* find end of optional destination */
  564.             for (dp=cp; *dp && *dp != ' ' && *dp != '\t' && *dp != '\n'; dp++) ;
  565.             if (*dp) *dp = '\0';
  566.  
  567.             cp = strdup(cp);
  568.             /* open the index file */
  569.             if((idx=open(fn,READBINARY)) != -1) {
  570.                 /* check if there are any messages in this area
  571.                  * that need to be forwarded.
  572.                  */
  573.                 if(read_header(idx,&hdr) != -1) {
  574.                     for(i=1; i<=f.m->nmsgs; i++) {
  575.                         pwait(NULL);
  576.                         if(read_index(idx,&f.ind) == -1) {
  577.                             err = 1;
  578.                             break;
  579.                         }
  580.                         if(sendmsgtobbs(&f, i, cp) == -1) {
  581.                             err = 1;        /* abort */
  582.                             break;
  583.                         }
  584.                         /* Done with this index, clear it */
  585.                         default_index(f.m->area,&f.ind);
  586.                         scanmail(f.m);
  587.                     }
  588.                 }
  589.                 close(idx);
  590.                 idx = 0;
  591.             }
  592.             if(f.m->mfile) {
  593.                 fclose(f.m->mfile);
  594.                 f.m->mfile = NULL;
  595.             }
  596.             free(cp);
  597.         }
  598.         fclose(f.m->tfile);
  599.         f.m->tfile = NULLFILE;
  600.         if(*oldarea != '\0')
  601.             changearea(f.m,oldarea);
  602.     }
  603.     default_index("",&f.ind);
  604.     if(f.m->state == MBX_FORWARD)
  605.         return 0;
  606.     tputs("*** Done\n");
  607. #ifdef notdef
  608.     /* Can't do this with polling anymore */
  609.     if((f.m->sid & MBX_RLI_SID))      /* disconnect if it is a W0RLI bbs */
  610.         return domboxbye(0,NULL,f.m);
  611. #endif
  612.     return 0;
  613. }
  614.   
  615. /* Read the forward file for a record for the connected BBS. If found,
  616.  * return 1 if this is the right time to forward, m->tfile is left pointing
  617.  * at the first message area to be forwarded.
  618.  */
  619. static int
  620. fwdinit(m)
  621. struct mbx *m;
  622. {
  623.     char host[80];
  624.     int start = 1;
  625.   
  626.     if((m->tfile = fopen(Forwardfile,READ_TEXT)) == NULLFILE)
  627.         return -1;
  628.   
  629.     while(fgets(m->line,MBXLINE,m->tfile) != NULLCHAR) {
  630.         if(*m->line == '\n')
  631.             continue;
  632.         /* lines starting with '-' separate the forwarding records */
  633.         if(*m->line == '-') {
  634.             start = 1;
  635.             continue;
  636.         }
  637.         if(start) {
  638.             start = 0;
  639.             /* get the name of this forwarding record */
  640.             findident(m->line,1,host);
  641.             if(stricmp(m->name,host) == 0) {
  642.                 if(!timeok(m->line))
  643.                     break;
  644.                 /* eat the connect command line */
  645.                 fgets(m->line,MBXLINE,m->tfile);
  646.                 return 0;
  647.             }
  648.         }
  649.     }
  650.     fclose(m->tfile);
  651.     m->tfile = NULLFILE;
  652.     return -1;
  653. }
  654. /* Read the forward file for a record for the connected BBS. If found,
  655.  * determine if this is the right time to forward, and return the command
  656.  * line to establish a forwarding connection. m->tfile is left pointing
  657.  * at the first message area to be forwarded.
  658.  */
  659. static char *
  660. fwdanybbs(m,poll)
  661. struct mbx *m;
  662. int *poll;
  663. {
  664.     char host[80];
  665.     int start = 1,i;
  666.   
  667.     if(m->tfile == NULLFILE && (m->tfile = fopen(Forwardfile,READ_TEXT))
  668.         == NULLFILE)
  669.         return NULLCHAR;
  670.     *poll = 0;  /* Default to no polling */
  671.     while(fgets(m->line,MBXLINE,m->tfile) != NULLCHAR) {
  672.         if(*m->line == '\n')
  673.             continue;
  674.         /* lines starting with '-' separate the forwarding records */
  675.         if(*m->line == '-') {
  676.             start = 1;
  677.             continue;
  678.         }
  679.         if(start) {
  680.             start = 0;
  681.             /* get the name of this forwarding record */
  682.             findident(m->line,1,host);
  683.             strcpy(m->name,host);
  684.             if(!timeok(m->line))
  685.                 continue;       /* too late or too early */
  686.             /* Check for polling - WG7J */
  687.             i=2;
  688.             findident(m->line,2,host);
  689.             while(*host) {
  690.                 if(*host == 'P' || *host == 'p') {
  691.                     *poll = 1;
  692.                     break;
  693.                 }
  694.                 i++;
  695.                 findident(m->line,i,host);
  696.             }
  697.             /* get the connect command line */
  698.             fgets(m->line,MBXLINE,m->tfile);
  699.             return strdup(m->line);
  700.         }
  701.     }
  702.     fclose(m->tfile);
  703.     m->tfile = NULLFILE;
  704.     return NULLCHAR;
  705. }
  706.   
  707. /* get any groups of four digits that specify the begin and ending hours of
  708.  * forwarding. Returns 1 if forwarding may take place.
  709.  */
  710. static int
  711. timeok(line)
  712. char *line;
  713. {
  714.     char hours[80], *now;
  715.     long t;
  716.     int t1, t2, pos = 2;
  717.     findident(line,pos++,hours);
  718.     if(*hours == '\0' || *hours == 'P' || *hours == 'p')
  719.         return 1;       /* no digits default to 0023, ie. anytime */
  720.     time(&t);
  721.     now = ctime(&t) + 11;
  722.     *(now + 2) = '\0';
  723.     while(*hours != '\0') {
  724.         t1 = (*hours - '0') * 10 + (*(hours+1) - '0');
  725.         t2 = (*(hours+2) - '0') * 10 + (*(hours+3) - '0');
  726.         if(atoi(now) >= t1 && atoi(now) <= t2)
  727.             return 1;               /* right in time */
  728.         findident(line,pos++,hours);    /* get next group if any */
  729.         if(*hours == 'P' || *hours == 'p')
  730.             return 0;
  731.     }
  732.     return 0;       /* too early or too late */
  733. }
  734.   
  735. int
  736. dombtimer(argc,argv,p)
  737. int argc;
  738. char *argv[];
  739. void *p;
  740. {
  741.     if(argc < 2){
  742.         tprintf("Forwarding timer: %lu/%lu server %s.\n",
  743.         read_timer(&fwdtimer)/1000L,
  744.         dur_timer(&fwdtimer)/1000L,
  745.         FwdProc != NULLPROC ? "started":"stopped");
  746.         return 0;
  747.     }
  748.     fwdtimer.func = (void (*)__ARGS((void *)))fwdtick;/* what to call on timeout */
  749.     fwdtimer.arg = NULL;            /* dummy value */
  750.     set_timer(&fwdtimer,atol(argv[1])*1000L); /* set timer duration */
  751.     pwait(NULL);
  752.     if (FwdProc != NULLPROC)    /* if someone is listening */
  753.         start_timer(&fwdtimer);     /* fire it up */
  754.     else
  755.         if(dur_timer(&fwdtimer) != 0)
  756.             tputs("Warning: forward server not started.\n");
  757.     return 0;
  758. }
  759.   
  760. int
  761. dombkick(argc,argv,p)
  762. int argc;
  763. char *argv[];
  764. void *p;
  765. {
  766.     if (FwdProc == NULLPROC) {
  767.         tputs("Forward server not started\n");
  768.         return 1;
  769.     }
  770.     psignal(&fwdtimer,0);
  771.     return 0;
  772. }
  773.   
  774. /* called when the forward timer expires or explicitly by dombkick() */
  775. /* MDMII: fwdproc is the old fwdtick.   But, since it can call pause, which is
  776.  * very very bad for timer functions :-( this has been converted to a server.
  777.  */
  778. static void
  779. fwdtick(v)
  780. void *v;
  781. {
  782.     psignal(&fwdtimer,0);           /* awake the forwarder */
  783.     start_timer(&fwdtimer);     /* and restart the timer */
  784. }
  785.   
  786. /* the main process for the mailbox forwarder */
  787. int
  788. fwdstart(argc,argv,p)
  789. int argc;
  790. char *argv[];
  791. void *p;
  792. {
  793.     if (FwdProc != NULLPROC)
  794.         return 0;       /* already started */
  795.   
  796.     FwdProc = Curproc;      /* set our flag */
  797.   
  798.     psignal(Curproc,0);     /* don't wait on us */
  799.   
  800.     start_timer(&fwdtimer);     /* start timer (ignored if 0) */
  801.   
  802.     for (;!pwait(&fwdtimer);)   /* wait for someone to tell us to try */
  803.         if (availmem() > Memthresh)
  804.             fwdproc();
  805.         else if(Mtrace)
  806.             tputs("fwd: forwarding skipped due to low memory\n");
  807.   
  808.     FwdProc = NULLPROC;     /* we are exiting */
  809.     return 0;           /* alerted from somewhere */
  810. }
  811.   
  812. /* (attempt to) kill the forwarder process */
  813. int
  814. fwd0(argc,argv,p)
  815. int argc;
  816. char *argv[];
  817. void *p;
  818. {
  819.     int i, max;         /* max attempts */
  820.   
  821.     stop_timer(&fwdtimer);      /* no more timer awakes */
  822.     max = 1;            /* Maximum attempts */
  823.     if (argc > 2)
  824.         setint(&max,NULLCHAR,argc,argv);
  825.   
  826.     for(i=0;i<max && FwdProc != NULLPROC;i++) {
  827.         alert(FwdProc,1);   /* signal regardless of location */
  828.         pwait(NULL);        /* let it see the alert */
  829.     }
  830.   
  831.     stop_timer(&fwdtimer);      /* in case timer tick restarted it */
  832.     return 0;
  833. }
  834.   
  835. /* MDMII: This is the old fwdtick function */
  836. static void
  837. fwdproc(void)
  838. {
  839.     char *cc, *cp, *fp;
  840.     struct mbx *m;
  841.     struct fwdbbs *bbs;
  842.     struct indexhdr hdr;
  843.     struct mailindex ind;
  844.     int i, idx, bulletin, poll,skip = 0;
  845.     char fn[FILE_PATH_SIZE];
  846.   
  847.     if(Mtrace)
  848.         tputs("mbox: fwd started\n");
  849.     if((m = newmbx()) == NULLMBX){
  850.         if(Mtrace)
  851.             tputs("fwd: no new mbox\n");
  852.         return;
  853.     }
  854.     m->user = Curproc->output;
  855.     m->state = MBX_TRYING;
  856.     memset(&ind,0,sizeof(struct mailindex));
  857.     while((cc = fwdanybbs(m,&poll)) != NULLCHAR) {
  858.         if(isconnbbs(m)) { /* already connected to this BBS, skip it */
  859.             skip = 1;
  860.             if(Mtrace)
  861.                 tprintf("fwd: %s already connected\n",m->name);
  862.         }
  863.         /* If we poll, there is no need to check message area, since this
  864.          * is also done later. It will speed things up here - WG7J
  865.          */
  866.         if(!skip && poll) {
  867.             if(Mtrace)
  868.                 tprintf("fwd: polling %s\n",m->name);
  869.             newproc("Mbox forwarding", 2048,startfwd, 0, (void *)cc,
  870.             (void *)strdup(m->name),0);
  871.             cc = NULLCHAR;
  872.             skip = 1;
  873.         }
  874.         if(!skip && Mtrace)
  875.             tprintf("fwd: %s - checking for messages\n",m->name);
  876.         while(fgets(m->line,MBXLINE,m->tfile) != NULLCHAR) {
  877.             pwait(NULL);
  878.             if(*m->line == '-') {   /* end of record reached */
  879.                 skip = 0;
  880.                 break;
  881.             }
  882.             if((cp = strchr(m->line,' ')) != NULLCHAR)
  883.                 *cp = '\0';
  884.             if((cp = strchr(m->line,'\t')) != NULLCHAR)
  885.                 *cp = '\0';
  886.             if(skip || *m->line == '\0' || *m->line == '#' || *m->line == '.' || \
  887.                 *m->line == '+' || *m->line == '@' || *m->line == '&')
  888.                 continue;
  889.             rip(m->line);
  890.             bulletin = isarea(m->line);     /* public area */
  891.             sprintf(fn,"%s/%s.ind",Mailspool,m->line);
  892.             if((idx=open(fn,READBINARY)) != -1) {
  893.                 /* check if there are any messages in this area
  894.                  * that need to be forwarded.
  895.                  */
  896.                 if(read_header(idx,&hdr) == -1)
  897.                     hdr.msgs = 0;
  898.                 for(i=1; i<=hdr.msgs; i++) {
  899.                     pwait(NULL);
  900.                     /* Done with this index, clear it */
  901.                     default_index("",&ind);
  902.                     if(read_index(idx,&ind) == -1)
  903.                         break; /* Should not happen ! */
  904.                     /* Apply same tests as in makecl() */
  905.                     if(ind.status & BM_HOLD) continue;
  906.                     if(bulletin) {
  907.                         for(bbs = ind.bbslist;bbs;bbs=bbs->next)
  908.                             if(!stricmp(bbs->call,m->name))
  909.                                 break;
  910.                         if(bbs)
  911.                             continue;
  912.                     } else if(ind.status & BM_READ)
  913.                         continue;
  914.                     if(ind.from) {    /* Don't fwd back to originator */
  915.                         fp=strdup(ind.from);
  916.                         if((cp=strchr(fp,'@')) != NULL)
  917.                             *cp = '\0';
  918.                         if((cp=strchr(fp,'%')) != NULL)
  919.                             *cp = '\0';
  920.                         if(strstr(fp,m->name) != NULL) {
  921.                             free(fp);
  922.                             continue;
  923.                         }
  924.                         free(fp);
  925.                     }
  926.                     if(Mtrace)
  927.                         tprintf("fwd: starting %s (%s,#%d)\n",m->name, m->line, i);
  928.                     newproc("Mbox forwarding", 2048,
  929.                     startfwd, 0, (void *)cc,
  930.                     (void *)strdup(m->name),0);
  931.                     skip = 1;
  932.                     cc = NULLCHAR;
  933.                     break;
  934.                 }
  935.                 /* Done with this index, clear it */
  936.                 default_index("",&ind);
  937.                 close(idx);
  938.             }
  939.         }
  940.         free(cc);
  941.     }
  942.     default_index("",&ind);
  943.     usesock(Curproc->output);   /* compensate for close_s() in exitbbs */
  944.     exitbbs(m);
  945. }
  946.   
  947. /* returns 1 if m->name matches the name of another connected mailbox. */
  948. static int
  949. isconnbbs(m)
  950. struct mbx *m;
  951. {
  952.     struct mbx *mp;
  953.   
  954.     for(mp=Mbox;mp;mp=mp->next)
  955.         if((stricmp(mp->name,m->name) == 0) && (mp->state != MBX_TRYING) )
  956.             return 1;
  957.     return 0;
  958. }
  959.   
  960. /* possible commands on the command line in the forwarding file */
  961. static struct cmds cfwdcmds[] = {
  962.     "tcp",          openconn,       0, 0, NULLCHAR,
  963.     "telnet",       openconn,       0, 0, NULLCHAR,
  964. #ifdef AX25
  965.     "ax25",         openconn,       0, 0, NULLCHAR,
  966.     "connect",      openconn,       0, 0, NULLCHAR,
  967. #endif
  968. #ifdef NETROM
  969.     "netrom",       openconn,       0, 0, NULLCHAR,
  970. #endif
  971.     NULLCHAR
  972. };
  973.   
  974. int FwdUsers;
  975.   
  976. void exitfwd(struct mbx *m) {
  977.     FwdUsers--;
  978.     if(m->state != MBX_TRYING) log(m->user,"MBOX fwd exit: %s",m->name); /* N5KNX: log exits */
  979.     exitbbs(m);
  980. }
  981.   
  982. /* this function is called whenever the forwarding timer expires */
  983. static void
  984. startfwd(a,v1,v2)
  985. int a;
  986. void *v1, *v2;
  987. {
  988.     struct mbx *m;
  989.     char *cc;
  990.     int32 timeout;
  991.     int rval;
  992.     char *cp;
  993.     char Continue[MBXLINE];
  994.   
  995.     cc = (char *) v1;
  996.     if((m = newmbx()) == NULLMBX) {
  997.         free(cc);
  998.         free((char *)v2);
  999.         return;
  1000.     }
  1001.     FwdUsers++;
  1002.     strcpy(m->name,(char *)v2);
  1003.     free((char *)v2);
  1004.     m->state = MBX_TRYING;
  1005.     /* open the connection, m->user will be the new socket */
  1006.     if(cmdparse(cfwdcmds,cc,(void *)m) == -1) {
  1007.         free(cc);
  1008.         usesock(Curproc->output);   /* compensate for close_s() in exitbbs */
  1009.         exitfwd(m);
  1010.         return;
  1011.     }
  1012.     free(cc);
  1013.     m->state = MBX_FORWARD;
  1014.     sockowner(m->user,Curproc);
  1015.     close_s(Curproc->output);
  1016.     close_s(Curproc->input);
  1017.     /* m->user will be closed automatically when this process exits */
  1018.     Curproc->output = Curproc->input = m->user;
  1019.     /* We'll do our own flushing right before we read input */
  1020.     setflush(m->user,-1);
  1021.   
  1022.     if(fwdinit(m) == -1) {
  1023.         /* it is probably not the right time to forward anymore */
  1024.         exitfwd(m);
  1025.         return;
  1026.     }
  1027.     /* read the connect script. Lines starting with a dot will be sent
  1028.      * to the remote BBS.
  1029.      */
  1030.     Continue[0] = '\0';
  1031.     while((cp=fgets(m->line,MBXLINE,m->tfile)) != NULLCHAR) {
  1032.         /* Expanded to do timeouts, and return string recognition - WG7J */
  1033.         switch(*m->line) {
  1034.             case '.':               /* send this line */
  1035.                 tputs(m->line + 1);
  1036.                 if(Mtrace)
  1037.                     printf("fwd: %s > %s\n",m->name,m->line+1);
  1038.                 Continue[0] = '\0';         /* reset reply string */
  1039.                 break;
  1040.             case '#':               /* comment line, ignore */
  1041.                 break;
  1042.             case '+':               /* string upon wich we continue ! */
  1043.                 strcpy(Continue,m->line+1);
  1044.                 rip(Continue);              /* get rid of \n */
  1045.                 break;
  1046.             case '&':               /* Wait a certain number of seconds */
  1047.                 timeout = atol(m->line+1);
  1048.                 pause(timeout * 1000L);
  1049.                 break;
  1050.             case '@':               /* string that sets timeout */
  1051.                 timeout = atol(m->line+1);
  1052.                 if(timeout)                 /* if a valid conversion */
  1053.                     timeout *= 1000;        /* in ms ! */
  1054.                 else
  1055.                     timeout = 90*1000L;     /* default to 1.5 minutes */
  1056.                 if(Mtrace)
  1057.                     printf("fwd: %s, wait %ld < %s\n",m->name,timeout/1000,Continue);
  1058.             /* Now do the actual response interpretations */
  1059.                 alarm(timeout);
  1060.                 rval = recvline(m->user,m->line,MBXLINE);
  1061.                 alarm(0L);
  1062.             /* Did we timeout, or connection disappear ? */
  1063.                 if(Mtrace) {
  1064.                     printf("fwd: %s, rx %d",m->name,rval);
  1065.                     if(rval >= 0)
  1066.                         printf(", %s",m->line);
  1067.                     else
  1068.                         putchar('\n');
  1069.                 }
  1070.                 if((rval < 0) || (strstr(m->line,Continue) == NULLCHAR)) {
  1071.                     if(Mtrace)
  1072.                         printf("fwd: %s, aborted!\n",m->name);
  1073.                     exitfwd(m);
  1074.                     return;
  1075.                 }
  1076.                 Continue[0] = '\0';         /* reset reply string */
  1077.                 break;
  1078.             default:        /* must be the end of the script */
  1079.                 goto go_on;
  1080.         }
  1081.   
  1082.         usflush(m->user);   /* send it, if any */
  1083.     }
  1084.     /* Now we've past all in-between stuff, go talk to the bbs ! */
  1085.     go_on:
  1086.     usflush(m->user);
  1087.     fclose(m->tfile);
  1088.     m->tfile = NULLFILE;
  1089.   
  1090.     /* make sure there is something left ! */
  1091.     if(cp == NULLCHAR) {
  1092.         if(Mtrace)
  1093.             puts("fwd: forward.bbs error!");
  1094.         exitfwd(m);
  1095.         return;
  1096.     }
  1097.     if(Mtrace)
  1098.         printf("fwd: %s, script done\n",m->name);
  1099.   
  1100.     /* read the initial output from the bbs, looking for the SID */
  1101.     for(;;) {
  1102.         if(recvline(m->user,m->line,MBXLINE) == -1) {
  1103.             exitfwd(m);
  1104.             return;
  1105.         }
  1106.         if(ISPROMPT(m->line))
  1107.             break;
  1108.         if(*m->line == '[') {           /* parse the SID */
  1109.             rip(m->line);
  1110.             mbx_parse(m);
  1111.             continue;
  1112.         }
  1113.     }
  1114.     /* Now sync the two ends as telnet password messes them up */
  1115.     if(socklen(m->user,0))          /* discard any remaining input */
  1116.         recv_mbuf(m->user,NULL,0,NULLCHAR,0);
  1117.   
  1118.     /* send our SID if the peer announced its SID */
  1119.     if(m->sid & MBX_SID) {
  1120.         tputs(MboxId);
  1121.         usflush(m->user);
  1122.         for(;;) {
  1123.             if(recvline(m->user,m->line,MBXLINE) == -1) {
  1124.                 exitfwd(m);
  1125.                 return;
  1126.             }
  1127.             if(ISPROMPT(m->line))
  1128.                 break;
  1129.         }
  1130.     }
  1131.     /* start the actual forwarding */
  1132.     dorevfwd(0,NULL,(void *)m);
  1133.     /* ask for reverse forwarding or just disconnect */
  1134.     if(((m->sid & MBX_SID) && tputs("F>\n") == -1) ||
  1135.     (m->sid & MBX_SID) == 0) {
  1136.         exitfwd(m);
  1137.         /* close_s(Curproc->output); exitfwd() calls exitbbs() which does this! */
  1138.         return;
  1139.     }
  1140.     usflush(m->user);
  1141.     /* parse the commands that are are received during reverse
  1142.      * forwarding.
  1143.      */
  1144.     while(recvline(m->user,m->line,MBXLINE) > 0) {
  1145.         rip(m->line);
  1146.         if(mbx_parse(m) == -2)   /* got the "*** Done" command */
  1147.             break;
  1148.         tputs("F>\n");
  1149.         usflush(m->user);
  1150.     }
  1151.     exitfwd(m);
  1152.     /* close_s(Curproc->output); exitfwd() calls exitbbs() which does this! */
  1153. }
  1154.   
  1155. /* open a network connection based upon information in the cc line.
  1156.  * m->user is set to the socket number.
  1157.  */
  1158. static int
  1159. openconn(argc,argv,p)
  1160. int argc;
  1161. char *argv[];
  1162. void *p;
  1163. {
  1164.     struct mbx *m;
  1165.     char sock[MAXSOCKSIZE], alias[AXBUF];
  1166.     struct nrroute_tab *rp;
  1167.     union sp sp;
  1168.     int len;
  1169.     char *remote;
  1170.   
  1171.     m = (struct mbx *)p;
  1172.     sp.p = sock;
  1173.     if(argc < 2) {
  1174.         if(Mtrace)
  1175.             tputs("fwd: connect command error\n");
  1176.         return -1;
  1177.     }
  1178.     remote = argv[1];
  1179.     switch(*argv[0]) {
  1180.         case 't':
  1181.             sp.in->sin_family = AF_INET;
  1182.             if((sp.in->sin_addr.s_addr = resolve(argv[1])) == 0) {
  1183.                 if(Mtrace)
  1184.                     tprintf("fwd: telnet - unknown host %s\n",argv[1]);
  1185.                 return -1;
  1186.             }
  1187.         /* get the optional port number */
  1188.             if(argc > 2)
  1189.                 sp.in->sin_port = atoip(argv[2]);
  1190.             else
  1191.                 sp.in->sin_port = IPPORT_TELNET;
  1192.             if((m->user = socket(AF_INET,SOCK_STREAM,0)) == -1) {
  1193.                 if(Mtrace)
  1194.                     tputs("fwd: unable to open telnet socket\n");
  1195.                 return -1;
  1196.             }
  1197.             len = sizeof(*sp.in);
  1198.             m->family = AF_INET; /*So the user list will be correct! - WG7J */
  1199.             break;
  1200. #ifdef AX25
  1201.         case 'a':
  1202.         case 'c':       /* allow 'c' for 'connect' as well */
  1203.             if(argc < 3) {
  1204.                 if(Mtrace)
  1205.                     tprintf("fwd: connect syntax error - %s %s ?\n",argv[0],argv[1]);
  1206.                 return -1;
  1207.             }
  1208.             sp.ax->sax_family = AF_AX25;
  1209.             strncpy(sp.ax->iface,argv[1],ILEN); /* the interface name */
  1210.             setcall(sp.ax->ax25_addr,argv[2]); /* the remote callsign */
  1211.         /* no digipeaters for now, use the "ax25 route add" command */
  1212.             if((m->user = socket(AF_AX25,SOCK_STREAM,0)) == -1) {
  1213.                 if(Mtrace)
  1214.                     tputs("fwd: Unable to open ax25 socket\n");
  1215.                 return -1;
  1216.             }
  1217.             len = sizeof(*sp.ax);
  1218.             m->family = AF_AX25; /*So the user list will be correct! - WG7J */
  1219.             remote = argv[2];
  1220.             break;
  1221. #endif /* AX25 */
  1222. #ifdef NETROM
  1223.         case 'n':
  1224.     /* See if the requested destination could be an alias, and
  1225.      * use it if it is.  Otherwise assume it is an AX.25
  1226.      * address.
  1227.      */
  1228.             putalias(alias,argv[1],0);
  1229.             strupr(argv[1]);
  1230.             if ((rp = find_nrboth(alias,argv[1])) == NULLNRRTAB)  {
  1231.                 if(Mtrace)
  1232.                     tprintf("fwd: Netrom route unavailable - %s\n",argv[1]);
  1233.                 return -1;
  1234.             }
  1235.     /* Setup the local side of the connection */
  1236.             sp.nr->nr_family = AF_NETROM;
  1237.             len = sizeof(*sp.nr);
  1238.             if((m->user = socket(AF_NETROM,SOCK_SEQPACKET,0)) == -1) {
  1239.                 if(Mtrace)
  1240.                     tprintf("fwd: unable to open netrom socket - %s\n",argv[1]);
  1241.   
  1242.                 return -1;
  1243.             }
  1244.             memcpy(sp.nr->nr_addr.user,Nr4user,AXALEN);
  1245.             memcpy(sp.nr->nr_addr.node,Nr_iface->hwaddr,AXALEN);
  1246.             bind(m->user,sp.p,len);
  1247.   
  1248.     /* Now the remote side */
  1249.             memcpy(sp.nr->nr_addr.node,rp->call,AXALEN) ;
  1250.     /* The user callsign of the remote station is never
  1251.          * used by NET/ROM, but it is needed for the psocket() call.
  1252.          */
  1253.             memcpy(sp.nr->nr_addr.user,rp->call,AXALEN) ;
  1254.   
  1255.             m->family = AF_NETROM; /*So the user list will be correct! - WG7J */
  1256.             break;
  1257. #endif /* NETROM */
  1258.         default:
  1259.             if(Mtrace)
  1260.                 tprintf("fwd: Invalid connect mode - %s\n",argv[0]);
  1261.   
  1262.             return -1;
  1263.     }
  1264.     sockmode(m->user,SOCK_ASCII);
  1265.     if(connect(m->user,sp.p,len) == -1) {
  1266.         log(m->user,"MBOX fwd failed: %s - %s errno %d",
  1267.         remote,sockerr(m->user),errno);
  1268.         if(Mtrace)
  1269.             tprintf("fwd: Connection failed to %s\n",remote);
  1270.         close_s(m->user);
  1271.         return -1;
  1272.     }
  1273.     return m->user;
  1274. }
  1275.   
  1276. #endif /*MBFWD*/
  1277.